import logging
import jwt
import time
from config import APP, SUBJECT, DEFAULT_TOKEN_SECRET
from libs.redis_wrapper import RedisWrapper
from utils.db_util import CreateEngine


class Token(object):

    @staticmethod
    def get_secret():
        return DEFAULT_TOKEN_SECRET

    @staticmethod
    def generate_agent_jwt(username, password, expire_in=7200):
        secret = Token.get_secret()
        payload = {
            'exp': int(time.time()) + expire_in,
            'username': username,
            'password': password,
        }
        headers = {
            'typ': 'JWT',
            'alg': 'HS256'  # 声明所使用的算法
        }
        jwt_token = jwt.encode(
            payload,
            secret,  # 进行加密签名的密钥
            headers=headers  # json web token 数据结构包含两部分，payload（有效载体），headers（标头）
        )  # python3 编码后得到 bytes，再进行解码（指明解码的格式），得到一个str
        return jwt_token

    @staticmethod
    def generate_jwt(app, subject, name, username, project_list, mobile="", mail="", grant_type=None, expire_in=7200):
        secret = Token.get_secret()
        # payload 有效载体
        payload = {
            'exp': int(time.time()) + expire_in,
            'name': name,
            'username': username,
            'mobile': mobile,
            'project_list': project_list,
            'mail': mail,
            'app': app,
            'sub': subject
        }
        if grant_type:
            payload['grant_type'] = grant_type
        # headers
        headers = {
            'typ': 'JWT',
            'alg': 'HS256'  # 声明所使用的算法
        }
        jwt_token = jwt.encode(
            payload,
            secret,  # 进行加密签名的密钥
            # algorithm='HS256',    # 指明签名算法方式，默认也是HS256
            headers=headers  # json web token 数据结构包含两部分，payload（有效载体），headers（标头）
        )  # python3 编码后得到 bytes，再进行解码（指明解码的格式），得到一个str
        return jwt_token if isinstance(jwt_token, str) else jwt_token.decode()

    @staticmethod
    def decode_jwt(token):
        """
        解密token信息
        :param token: token
        :return: 返回解密信息
        """
        secret = Token.get_secret()
        logging.info(f"secret:{secret}")
        try:
            # 需要解析的 jwt 密钥 使用和加密时相同的算法
            data = jwt.decode(token, secret, algorithms=['HS256'])
        except Exception as e:
            # 如果 jwt 被篡改过；或者算法不正确；如果设置有效时间，过了有效期；或者密钥不相同；都会抛出相应的异常
            logging.info(f"token:{token}")
            logging.info("错误的jwt：%s" % str(e))
            return None
        else:
            if data.get('grant_type', ''):
                return None
        return data

    @staticmethod
    def decode_refresh_jwt(token):
        """
        解密刷新token信息
        :param token: token
        :param secret: 密钥
        :return: 返回解密信息
        """
        secret = Token.get_secret()
        try:
            # 需要解析的 jwt 密钥 使用和加密时相同的算法
            data = jwt.decode(token, secret, algorithms=['HS256'])
        except Exception as e:
            # 如果 jwt 被篡改过；或者算法不正确；如果设置有效时间，过了有效期；或者密钥不相同；都会抛出相应的异常
            import traceback
            traceback.print_exc()
            return None
        else:
            if data.get('grant_type', '') != 'refresh':
                return None
        return data

    @staticmethod
    def get_token(**kwargs):
        expire_in = 72000
        if 'expire_in' in kwargs:
            expire_in = kwargs['expire_in']
        refresh_expire_in = expire_in * 12 * 30
        if 'refresh_expire_in' in kwargs:
            refresh_expire_in = kwargs['refresh_expire_in']
        token = Token.generate_jwt(
            app=APP,
            subject=SUBJECT,
            project_list=[APP],
            name=kwargs.get("name", '--'),
            username=kwargs.get("username", '--'),
            mail=kwargs.get("mail", '--'),
            mobile=kwargs.get("mobile", '--'),
            expire_in=expire_in * 12 * 2
        )

        refresh_token = Token.generate_jwt(
            app=kwargs.get("app", APP),
            subject=kwargs.get("subject", SUBJECT),
            project_list=kwargs.get("project_list", []),
            name=kwargs.get("name", '--'),
            username=kwargs.get("username", '--'),
            mail=kwargs.get("mail", '--'),
            mobile=kwargs.get("mobile", '--'),
            expire_in=refresh_expire_in
        )

        return {
            'token': token,
            'refresh_token': refresh_token,
            'expire_in': expire_in,
            'name': kwargs.get('name', '--')
        }

    @staticmethod
    def get_agent_token(**kwargs):
        expire_in = 7200
        if 'expire_in' in kwargs:
            expire_in = kwargs['expire_in']
        refresh_expire_in = expire_in * 12 * 30
        if 'refresh_expire_in' in kwargs:
            refresh_expire_in = kwargs['refresh_expire_in']
        token = Token.generate_agent_jwt(
            username=kwargs.get("username", '--'),
            password=kwargs.get("phone", '--'),
            expire_in=expire_in * 12 * 1
        )
        refresh_token = Token.generate_agent_jwt(
            username=kwargs.get("username", '--'),
            password=kwargs.get("phone", '--'),
            expire_in=refresh_expire_in
        )

        return {
            'token': token,
            'refresh_token': refresh_token,
            'expire_in': expire_in
        }
